{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "source": [
    "import sys\n",
    "assert sys.version_info >= (3, 5)\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "mpl.rc('axes', labelsize=14)\n",
    "mpl.rc('xtick', labelsize=12)\n",
    "mpl.rc('ytick', labelsize=12)\n",
    "import tensorflow as tf\n",
    "from tensorflow import keras\n",
    "from sklearn.preprocessing import OneHotEncoder\n",
    "import pandas as pd\n",
    "from scipy import special\n",
    "from Clustering_Equalgrps.equal_groups import EqualGroupsKMeans\n",
    "\n",
    "np.random.seed(42)\n",
    "tf.random.set_seed(42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "M = 16\n",
    "M_sec = 4\n",
    "k = int(np.log2(M))\n",
    "n = 16\n",
    "TRAINING_SNR = 10 # snr = ebno * k/n\n",
    "SAMPLE_SIZE = 50000\n",
    "messages = np.random.randint(M, size=SAMPLE_SIZE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "one_hot_encoder = OneHotEncoder(sparse=False, categories=[range(M)])\n",
    "data_oneH = one_hot_encoder.fit_transform(messages.reshape(-1, 1))\n",
    "\n",
    "# Generate Training Data\n",
    "#x = tf.random.uniform(shape=[SAMPLE_SIZE], minval=0, maxval=M, dtype=tf.int64)\n",
    "#x_1h = tf.one_hot(x, M)\n",
    "#dataset = tf.data.Dataset.from_tensor_slices(x_1h)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def snr_to_noise(snrdb):\n",
    "    '''Transform snr to noise power'''\n",
    "    snr = 10**(snrdb/10)\n",
    "    noise_std = 1/np.sqrt(2*snr) # 1/np.sqrt(2*(k/n)*ebno) for ebno to noise\n",
    "    return noise_std"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "noise_std = snr_to_noise(TRAINING_SNR)\n",
    "noise_std_eve = snr_to_noise(7)\n",
    "\n",
    "# custom functions / layers without weights\n",
    "norm_layer = keras.layers.Lambda(lambda x: tf.divide(x, tf.sqrt(2*tf.reduce_mean(tf.square(x)))))\n",
    "shape_layer = keras.layers.Lambda(lambda x: tf.reshape(x, shape=[-1,2,n]))\n",
    "shape_layer2 = keras.layers.Lambda(lambda x: tf.reshape(x, shape=[-1,2*n]))\n",
    "channel_layer = keras.layers.Lambda(lambda x: \n",
    "                    tf.add(x, tf.random.normal(tf.shape(x), mean=0.0, stddev=noise_std)))\n",
    "channel_layer_eve = keras.layers.Lambda(lambda x: \n",
    "                    tf.add(x, tf.random.normal(tf.shape(x), mean=0.0, stddev=noise_std_eve)))\n",
    "\n",
    "encoder = keras.models.Sequential([\n",
    "            keras.layers.InputLayer(input_shape=[M]),\n",
    "            keras.layers.Dense(M, activation=\"elu\"),\n",
    "            keras.layers.Dense(2*n, activation=None),\n",
    "            shape_layer,\n",
    "            norm_layer])\n",
    "\n",
    "channel = keras.models.Sequential([channel_layer])\n",
    "channel_eve = keras.models.Sequential([channel_layer, channel_layer_eve])\n",
    "\n",
    "decoder_bob = keras.models.Sequential([\n",
    "                keras.layers.InputLayer(input_shape=[2,n]),\n",
    "                shape_layer2,\n",
    "                keras.layers.Dense(M, activation=\"elu\"),\n",
    "                keras.layers.Dense(M, activation=\"softmax\")\n",
    "                ])\n",
    "\n",
    "decoder_eve = keras.models.Sequential([\n",
    "                keras.layers.InputLayer(input_shape=[2,n]),\n",
    "                shape_layer2,\n",
    "                keras.layers.Dense(M, activation=\"elu\"),\n",
    "                keras.layers.Dense(M, activation=\"softmax\")\n",
    "                ])\n",
    "\n",
    "autoencoder_bob = keras.models.Sequential([encoder, channel, decoder_bob])\n",
    "autoencoder_eve = keras.models.Sequential([encoder, channel_eve, decoder_eve])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def B_Ber(input_msg, msg):\n",
    "    '''Calculate the Batch Bit Error Rate'''\n",
    "    pred_error = tf.not_equal(tf.argmax(msg, 1), tf.argmax(input_msg, 1))\n",
    "    bber = tf.reduce_mean(tf.cast(pred_error, tf.float32))\n",
    "    return bber"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def random_batch(X, batch_size=32):\n",
    "    idx = np.random.randint(len(X), size=batch_size) \n",
    "    return X[idx]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_encoding(M=16, n=1):\n",
    "    inp = np.eye(M, dtype=int)\n",
    "    coding = encoder.predict(inp)\n",
    "    fig = plt.figure(figsize=(4,4))\n",
    "    plt.plot(coding[:,0], coding[:, 1], \"b.\")\n",
    "    plt.xlabel(\"$x_1$\", fontsize=18)\n",
    "    plt.ylabel(\"$x_2$\", fontsize=18, rotation=0)\n",
    "    plt.grid(True)\n",
    "    plt.gca().set_ylim(-2, 2)\n",
    "    plt.gca().set_xlim(-2, 2)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_noisy_codeword(data):\n",
    "    rcvd_word = data[1:2000]\n",
    "    fig = plt.figure(figsize=(4,4))\n",
    "    plt.plot(rcvd_word[:,0], rcvd_word[:, 1], \"b.\")\n",
    "    #plt.plot(rcvd_word_eve[:,0], rcvd_word_eve[:, 1], 'or')    \n",
    "    plt.xlabel(\"$x_1$\", fontsize=18)\n",
    "    plt.ylabel(\"$x_2$\", fontsize=18, rotation=0)\n",
    "    plt.grid(True)\n",
    "    plt.gca().set_ylim(-2, 2)\n",
    "    plt.gca().set_xlim(-2, 2)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_epochs = 5\n",
    "batch_size = 200\n",
    "n_steps = len(data_oneH) // batch_size\n",
    "optimizer = keras.optimizers.Nadam(lr=0.005)\n",
    "loss_fn = keras.losses.categorical_crossentropy\n",
    "mean_loss = keras.metrics.Mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_loss(step, epoch, mean_loss, X_batch, y_pred, plot_encoding):\n",
    "    template = 'Iteration: {}, Epoch: {}, Loss: {:.5f}, Batch_BER: {:.5f}'\n",
    "    if step % 10 == 0:\n",
    "        print(template.format(step, epoch, mean_loss.result(), B_Ber(X_batch, y_pred)))\n",
    "        if plot_encoding:\n",
    "            test_encoding()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_batch_loss(epoch, mean_loss, X_batch, y_pred):\n",
    "        template_outer_loop = 'Interim result for Epoch: {}, Loss: {:.5f}, Batch_BER: {:.5f}'\n",
    "        print(template_outer_loop.format(epoch, mean_loss.result(), B_Ber(X_batch, y_pred)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_Bob(n_epochs=5, n_steps=20, plot_encoding=True, only_decoder=False):\n",
    "    for epoch in range(1, n_epochs + 1): \n",
    "        print(\"Training Bob in Epoch {}/{}\".format(epoch, n_epochs)) \n",
    "        for step in range(1, n_steps + 1):\n",
    "            X_batch  = random_batch(data_oneH, batch_size) \n",
    "            #X_batch  = dataset.batch(batch_size)\n",
    "            with tf.GradientTape() as tape:\n",
    "                y_pred = autoencoder_bob(X_batch, training=True)\n",
    "                main_loss = tf.reduce_mean(loss_fn(X_batch, y_pred))\n",
    "                loss = main_loss\n",
    "            if only_decoder:\n",
    "                gradients = tape.gradient(loss, decoder_bob.trainable_variables) \n",
    "                optimizer.apply_gradients(zip(gradients, decoder_bob.trainable_variables)) \n",
    "            else:\n",
    "                gradients = tape.gradient(loss, autoencoder_bob.trainable_variables) \n",
    "                optimizer.apply_gradients(zip(gradients, autoencoder_bob.trainable_variables)) \n",
    "            mean_loss(loss)\n",
    "            plot_loss(step, epoch, mean_loss, X_batch, y_pred, plot_encoding)\n",
    "        plot_batch_loss(epoch, mean_loss, X_batch, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_Eve(n_epochs=5, iterations=20, plot_encoding=True):\n",
    "    for epoch in range(1, n_epochs + 1): \n",
    "        print(\"Training Eve in Epoch {}/{}\".format(epoch, n_epochs)) \n",
    "        for step in range(1, n_steps + 1):\n",
    "            X_batch  = random_batch(data_oneH, batch_size) \n",
    "            with tf.GradientTape() as tape:\n",
    "                y_pred = autoencoder_eve(X_batch, training=True)\n",
    "                main_loss = tf.reduce_mean(loss_fn(X_batch, y_pred))\n",
    "                loss = main_loss\n",
    "            gradients = tape.gradient(loss, decoder_eve.trainable_variables) \n",
    "            optimizer.apply_gradients(zip(gradients, decoder_eve.trainable_variables)) \n",
    "            mean_loss(loss)\n",
    "            plot_loss(step, epoch, mean_loss, X_batch, y_pred, plot_encoding)\n",
    "        plot_batch_loss(epoch, mean_loss, X_batch, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def init_kmeans(symM=16, satellites=4, n=100):\n",
    "    '''Initializes equal sized clusters with the whole message set'''\n",
    "    inp = np.eye(symM, dtype=int)\n",
    "    unit_codewords = encoder.predict(inp)\n",
    "    kmeans = EqualGroupsKMeans(n_clusters=satellites)\n",
    "    kmeans.fit(unit_codewords.reshape(symM,2*n))\n",
    "    return kmeans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_mat(kmeans_labels, satellites=4, symM=16):\n",
    "    '''Generates the matrix for equalization of the input distribution on Eves side'''\n",
    "    gen_matrix = np.zeros((symM,symM))\n",
    "    for j in range(satellites):\n",
    "        for i in range(symM):\n",
    "            if kmeans_labels[i]==j:\n",
    "                for k in range(symM):\n",
    "                    if kmeans_labels[k] == j:\n",
    "                        gen_matrix[i,k] = 1/satellites;\n",
    "    gen_mat=tf.cast(gen_matrix, tf.float64)\n",
    "    return gen_mat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_Secure(kmeans_labels, n_epochs=5, iterations=20, alpha=0.7, plot_encoding=True):\n",
    "    '''This procedure trains the encoder to cluster the codewords,\n",
    "       based on the kmeans labels.\n",
    "       \n",
    "       Inputs: kmeans.labels_, epochs, iterations, alpha, plotting decision variable\n",
    "    '''\n",
    "    generator_matrix = generate_mat(kmeans_labels, M_sec, M)\n",
    "    for epoch in range(1, n_epochs + 1): \n",
    "        print(\"Training for Security in Epoch {}/{}\".format(epoch, n_epochs)) \n",
    "        for step in range(1, n_steps + 1):\n",
    "            X_batch  = random_batch(data_oneH, batch_size)\n",
    "            x_batch_s= tf.matmul(X_batch, generator_matrix)\n",
    "            with tf.GradientTape() as tape:\n",
    "                y_pred_bob = autoencoder_bob(X_batch, training=True)\n",
    "                y_pred_eve = autoencoder_eve(X_batch, training=False)\n",
    "                loss_bob = tf.reduce_mean(loss_fn(X_batch, y_pred_bob))    \n",
    "                loss_eve = tf.reduce_mean(loss_fn(x_batch_s, y_pred_eve))\n",
    "                loss_sec =  (1-alpha)*loss_bob + alpha*loss_eve\n",
    "            gradients = tape.gradient(loss_sec, autoencoder_bob.trainable_variables) \n",
    "            optimizer.apply_gradients(zip(gradients, autoencoder_bob.trainable_variables)) \n",
    "            mean_loss(loss_sec)\n",
    "            plot_loss(step, epoch, mean_loss, X_batch, y_pred_bob, plot_encoding)\n",
    "        plot_batch_loss(epoch, mean_loss, X_batch, y_pred_bob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# test msg sequence for normal encoding\n",
    "N_test = 150000\n",
    "test_msg = np.random.randint(M, size=N_test)\n",
    "one_hot_encoder = OneHotEncoder(sparse=False, categories=[range(M)])\n",
    "data_oh_normal = one_hot_encoder.fit_transform(test_msg.reshape(-1,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Test_AE(data):\n",
    "    '''Calculate Bit Error for varying SNRs'''\n",
    "    snr_range = np.linspace(0, 15, 30)\n",
    "    bber_vec_bob = [None] * len(snr_range)\n",
    "    bber_vec_eve = [None] * len(snr_range)\n",
    "        \n",
    "    for db in range(len(snr_range)):           \n",
    "        noise_std = snr_to_noise(snr_range[db])\n",
    "        noise_std_eve = snr_to_noise(7)\n",
    "        code_word = encoder.predict(data)\n",
    "        rcvd_word = code_word + tf.random.normal(tf.shape(code_word), mean=0.0, stddev=noise_std)\n",
    "        rcvd_word_eve = rcvd_word + \\\n",
    "                            tf.random.normal(tf.shape(rcvd_word), mean=0.0, stddev=noise_std_eve)\n",
    "        dcoded_msg_bob = decoder_bob.predict(rcvd_word)\n",
    "        dcoded_msg_eve = decoder_eve.predict(rcvd_word_eve)\n",
    "        bber_vec_bob[db] = B_Ber(data, dcoded_msg_bob)\n",
    "        bber_vec_eve[db] = B_Ber(data, dcoded_msg_eve)\n",
    "        print(f'Progress: {db+1} of {30} parts')\n",
    "        #test_noisy_codeword(rcvd_word)\n",
    "        #test_noisy_codeword(rcvd_word_eve)\n",
    "    return (snr_range, bber_vec_bob), (snr_range, bber_vec_eve)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "def satellite_labels(kmeans_labels, data_label, sats=8, data_size=150000):\n",
    "    '''Generate cloud/satelite codewords which utilizes the previously trained encoder.\n",
    "       It therefore takes a message vector of lower dimensionality and maps it to the higher\n",
    "       dimensional secure coding. The satelite codewords, i.e. co-sets are chosen randomly\n",
    "       according to the clusters.\n",
    "    '''\n",
    "    code_mat = np.zeros((sats, sats))\n",
    "    for sat in range(sats):\n",
    "        n = 0;\n",
    "        for index in range(M):\n",
    "            if kmeans_labels[index] == sat:\n",
    "                code_mat[sat, n] = index;\n",
    "                n = n + 1;\n",
    "    coded_label = np.zeros(data_size)\n",
    "    for i in range(data_size):\n",
    "        aux_var = data_label[i];\n",
    "        # pick a random row of column aux_var, i.e random symbol in the cluster\n",
    "        coded_label[i] = code_mat[np.random.randint(M_sec), aux_var];\n",
    "        \n",
    "    return coded_label, code_mat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sec_decoding(code_mat, pred_output, satellites, clusters):\n",
    "    '''Decodes the cloud signal encoding'''\n",
    "    sats = satellites\n",
    "    data = np.array(pred_output)\n",
    "    decoded_data = np.zeros(len(data))\n",
    "    for sample in range(len(data)):\n",
    "        cloud, msg = np.where(code_mat == data[sample])\n",
    "        decoded_data[sample] = msg\n",
    "    return decoded_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Test_secure_AE(coded_data, code_mat, real_data):\n",
    "    '''Calculate symbol error for varying SNRs'''\n",
    "    snr_range = np.linspace(0, 15, 30)\n",
    "    bber_vec_bob = [None] * len(snr_range)\n",
    "    bber_vec_eve = [None] * len(snr_range)\n",
    "        \n",
    "    for db in range(len(snr_range)):           \n",
    "        noise_std = snr_to_noise(snr_range[db])\n",
    "        noise_std_eve = snr_to_noise(7)\n",
    "        code_word = encoder.predict(coded_data)\n",
    "        rcvd_word = code_word + tf.random.normal(tf.shape(code_word), mean=0.0, stddev=noise_std)\n",
    "        rcvd_word_eve = rcvd_word + \\\n",
    "                            tf.random.normal(tf.shape(code_word), mean=0.0, stddev=noise_std_eve)\n",
    "        pred_msg_bob = decoder_bob.predict(rcvd_word)\n",
    "        pred_msg_eve = decoder_eve.predict(rcvd_word_eve)\n",
    "        decoded_msg_bob = sec_decoding(code_mat, np.array(tf.argmax(pred_msg_bob,1)),\n",
    "                                    M_sec, M_sec)\n",
    "        decoded_msg_eve = sec_decoding(code_mat, np.array(tf.argmax(pred_msg_eve,1)),\n",
    "                                    M_sec, M_sec)\n",
    "        bber_vec_bob[db] = np.mean(np.not_equal(decoded_msg_bob, real_data))\n",
    "        bber_vec_eve[db] = np.mean(np.not_equal(decoded_msg_eve, real_data))\n",
    "        print(f'Progress: {db+1} of {30} parts')\n",
    "        #test_noisy_codeword(rcvd_word)\n",
    "        #test_noisy_codeword(rcvd_word_eve)\n",
    "    return (snr_range, bber_vec_bob), (snr_range, bber_vec_eve)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training Bob in Epoch 1/5\n",
      "Iteration: 10, Epoch: 1, Loss: 2.42142, Batch_BER: 0.41000\n",
      "Iteration: 20, Epoch: 1, Loss: 1.82049, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 1, Loss: 1.37991, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 1, Loss: 1.08505, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 1, Loss: 0.88690, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 1, Loss: 0.74830, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 1, Loss: 0.64659, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 1, Loss: 0.56912, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 1, Loss: 0.50813, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 1, Loss: 0.45898, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 1, Loss: 0.41855, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 1, Loss: 0.38467, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 1, Loss: 0.35584, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 1, Loss: 0.33105, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 1, Loss: 0.30951, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 1, Loss: 0.29058, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 1, Loss: 0.27386, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 1, Loss: 0.25895, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 1, Loss: 0.24559, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 1, Loss: 0.23355, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 1, Loss: 0.22263, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 1, Loss: 0.21268, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 1, Loss: 0.20359, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 1, Loss: 0.19525, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 1, Loss: 0.18757, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 1, Loss: 0.18757, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 2/5\n",
      "Iteration: 10, Epoch: 2, Loss: 0.18047, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 2, Loss: 0.17388, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 2, Loss: 0.16776, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 2, Loss: 0.16206, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 2, Loss: 0.15673, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 2, Loss: 0.15174, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 2, Loss: 0.14706, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 2, Loss: 0.14266, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 2, Loss: 0.13852, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 2, Loss: 0.13461, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 2, Loss: 0.13092, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 2, Loss: 0.12742, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 2, Loss: 0.12410, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 2, Loss: 0.12096, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 2, Loss: 0.11797, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 2, Loss: 0.11512, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 2, Loss: 0.11241, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 2, Loss: 0.10982, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 2, Loss: 0.10735, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 2, Loss: 0.10499, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 2, Loss: 0.10273, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 2, Loss: 0.10056, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 2, Loss: 0.09849, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 2, Loss: 0.09650, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 2, Loss: 0.09459, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 2, Loss: 0.09459, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 3/5\n",
      "Iteration: 10, Epoch: 3, Loss: 0.09275, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 3, Loss: 0.09098, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 3, Loss: 0.08928, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 3, Loss: 0.08764, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 3, Loss: 0.08606, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 3, Loss: 0.08454, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 3, Loss: 0.08307, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 3, Loss: 0.08164, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 3, Loss: 0.08027, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 3, Loss: 0.07895, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 3, Loss: 0.07766, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 3, Loss: 0.07642, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 3, Loss: 0.07521, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 3, Loss: 0.07405, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 3, Loss: 0.07292, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 3, Loss: 0.07182, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 3, Loss: 0.07076, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 3, Loss: 0.06972, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 3, Loss: 0.06872, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 3, Loss: 0.06775, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 3, Loss: 0.06680, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 3, Loss: 0.06588, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 3, Loss: 0.06498, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 3, Loss: 0.06411, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 3, Loss: 0.06326, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 3, Loss: 0.06326, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 4/5\n",
      "Iteration: 10, Epoch: 4, Loss: 0.06243, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 4, Loss: 0.06163, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 4, Loss: 0.06084, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 4, Loss: 0.06008, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 4, Loss: 0.05933, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 4, Loss: 0.05860, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 4, Loss: 0.05789, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 4, Loss: 0.05720, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 4, Loss: 0.05652, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 4, Loss: 0.05586, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 4, Loss: 0.05522, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 4, Loss: 0.05459, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 4, Loss: 0.05397, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 4, Loss: 0.05337, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 4, Loss: 0.05278, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 4, Loss: 0.05220, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 4, Loss: 0.05164, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 4, Loss: 0.05108, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 4, Loss: 0.05054, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 4, Loss: 0.05001, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 4, Loss: 0.04950, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 4, Loss: 0.04899, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 4, Loss: 0.04849, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 4, Loss: 0.04800, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 4, Loss: 0.04753, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 4, Loss: 0.04753, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 5/5\n",
      "Iteration: 10, Epoch: 5, Loss: 0.04706, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 5, Loss: 0.04660, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 5, Loss: 0.04615, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 5, Loss: 0.04571, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 5, Loss: 0.04527, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 5, Loss: 0.04485, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 5, Loss: 0.04443, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 5, Loss: 0.04402, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 5, Loss: 0.04362, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 5, Loss: 0.04323, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 5, Loss: 0.04284, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 5, Loss: 0.04246, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 5, Loss: 0.04208, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 5, Loss: 0.04172, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 5, Loss: 0.04136, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 5, Loss: 0.04100, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 5, Loss: 0.04065, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 5, Loss: 0.04031, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 5, Loss: 0.03997, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 5, Loss: 0.03964, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 5, Loss: 0.03931, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 5, Loss: 0.03899, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 5, Loss: 0.03868, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 5, Loss: 0.03837, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 5, Loss: 0.03806, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 5, Loss: 0.03806, Batch_BER: 0.00000\n",
      "Training Eve in Epoch 1/4\n",
      "Iteration: 10, Epoch: 1, Loss: 0.04408, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 1, Loss: 0.04393, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 1, Loss: 0.04363, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 1, Loss: 0.04332, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 1, Loss: 0.04300, Batch_BER: 0.00000\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 60, Epoch: 1, Loss: 0.04269, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 1, Loss: 0.04238, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 1, Loss: 0.04208, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 1, Loss: 0.04177, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 1, Loss: 0.04147, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 1, Loss: 0.04118, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 1, Loss: 0.04089, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 1, Loss: 0.04060, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 1, Loss: 0.04031, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 1, Loss: 0.04003, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 1, Loss: 0.03976, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 1, Loss: 0.03948, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 1, Loss: 0.03921, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 1, Loss: 0.03895, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 1, Loss: 0.03868, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 1, Loss: 0.03842, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 1, Loss: 0.03817, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 1, Loss: 0.03791, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 1, Loss: 0.03766, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 1, Loss: 0.03742, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 1, Loss: 0.03742, Batch_BER: 0.00000\n",
      "Training Eve in Epoch 2/4\n",
      "Iteration: 10, Epoch: 2, Loss: 0.03717, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 2, Loss: 0.03693, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 2, Loss: 0.03669, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 2, Loss: 0.03646, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 2, Loss: 0.03622, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 2, Loss: 0.03600, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 2, Loss: 0.03577, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 2, Loss: 0.03555, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 2, Loss: 0.03533, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 2, Loss: 0.03511, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 2, Loss: 0.03489, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 2, Loss: 0.03468, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 2, Loss: 0.03447, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 2, Loss: 0.03426, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 2, Loss: 0.03406, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 2, Loss: 0.03385, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 2, Loss: 0.03365, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 2, Loss: 0.03346, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 2, Loss: 0.03326, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 2, Loss: 0.03306, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 2, Loss: 0.03287, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 2, Loss: 0.03268, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 2, Loss: 0.03250, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 2, Loss: 0.03231, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 2, Loss: 0.03213, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 2, Loss: 0.03213, Batch_BER: 0.00000\n",
      "Training Eve in Epoch 3/4\n",
      "Iteration: 10, Epoch: 3, Loss: 0.03195, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 3, Loss: 0.03177, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 3, Loss: 0.03159, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 3, Loss: 0.03142, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 3, Loss: 0.03125, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 3, Loss: 0.03108, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 3, Loss: 0.03091, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 3, Loss: 0.03074, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 3, Loss: 0.03057, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 3, Loss: 0.03041, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 3, Loss: 0.03025, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 3, Loss: 0.03009, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 3, Loss: 0.02993, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 3, Loss: 0.02977, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 3, Loss: 0.02962, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 3, Loss: 0.02946, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 3, Loss: 0.02931, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 3, Loss: 0.02916, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 3, Loss: 0.02901, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 3, Loss: 0.02886, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 3, Loss: 0.02872, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 3, Loss: 0.02857, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 3, Loss: 0.02843, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 3, Loss: 0.02829, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 3, Loss: 0.02815, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 3, Loss: 0.02815, Batch_BER: 0.00000\n",
      "Training Eve in Epoch 4/4\n",
      "Iteration: 10, Epoch: 4, Loss: 0.02801, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 4, Loss: 0.02787, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 4, Loss: 0.02773, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 4, Loss: 0.02760, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 4, Loss: 0.02746, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 4, Loss: 0.02733, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 4, Loss: 0.02720, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 4, Loss: 0.02707, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 4, Loss: 0.02694, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 4, Loss: 0.02681, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 4, Loss: 0.02669, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 4, Loss: 0.02656, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 4, Loss: 0.02644, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 4, Loss: 0.02631, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 4, Loss: 0.02619, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 4, Loss: 0.02607, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 4, Loss: 0.02595, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 4, Loss: 0.02583, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 4, Loss: 0.02572, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 4, Loss: 0.02560, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 4, Loss: 0.02549, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 4, Loss: 0.02537, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 4, Loss: 0.02526, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 4, Loss: 0.02515, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 4, Loss: 0.02504, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 4, Loss: 0.02504, Batch_BER: 0.00000\n",
      "Progress: 1 of 30 parts\n",
      "Progress: 2 of 30 parts\n",
      "Progress: 3 of 30 parts\n",
      "Progress: 4 of 30 parts\n",
      "Progress: 5 of 30 parts\n",
      "Progress: 6 of 30 parts\n",
      "Progress: 7 of 30 parts\n",
      "Progress: 8 of 30 parts\n",
      "Progress: 9 of 30 parts\n",
      "Progress: 10 of 30 parts\n",
      "Progress: 11 of 30 parts\n",
      "Progress: 12 of 30 parts\n",
      "Progress: 13 of 30 parts\n",
      "Progress: 14 of 30 parts\n",
      "Progress: 15 of 30 parts\n",
      "Progress: 16 of 30 parts\n",
      "Progress: 17 of 30 parts\n",
      "Progress: 18 of 30 parts\n",
      "Progress: 19 of 30 parts\n",
      "Progress: 20 of 30 parts\n",
      "Progress: 21 of 30 parts\n",
      "Progress: 22 of 30 parts\n",
      "Progress: 23 of 30 parts\n",
      "Progress: 24 of 30 parts\n",
      "Progress: 25 of 30 parts\n",
      "Progress: 26 of 30 parts\n",
      "Progress: 27 of 30 parts\n",
      "Progress: 28 of 30 parts\n",
      "Progress: 29 of 30 parts\n",
      "Progress: 30 of 30 parts\n",
      "Training for Security in Epoch 1/2\n",
      "Iteration: 10, Epoch: 1, Loss: 0.03211, Batch_BER: 0.00500\n",
      "Iteration: 20, Epoch: 1, Loss: 0.03541, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 1, Loss: 0.03831, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 1, Loss: 0.04103, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 1, Loss: 0.04368, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 1, Loss: 0.04623, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 1, Loss: 0.04874, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 1, Loss: 0.05118, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 1, Loss: 0.05358, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 1, Loss: 0.05591, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 1, Loss: 0.05825, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 1, Loss: 0.06054, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 1, Loss: 0.06282, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 1, Loss: 0.06508, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 1, Loss: 0.06729, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 1, Loss: 0.06948, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 1, Loss: 0.07166, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 1, Loss: 0.07382, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 1, Loss: 0.07595, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 1, Loss: 0.07807, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 1, Loss: 0.08014, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 1, Loss: 0.08219, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 1, Loss: 0.08425, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 1, Loss: 0.08628, Batch_BER: 0.00000\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 250, Epoch: 1, Loss: 0.08828, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 1, Loss: 0.08828, Batch_BER: 0.00000\n",
      "Training for Security in Epoch 2/2\n",
      "Iteration: 10, Epoch: 2, Loss: 0.09027, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 2, Loss: 0.09224, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 2, Loss: 0.09421, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 2, Loss: 0.09614, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 2, Loss: 0.09806, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 2, Loss: 0.09996, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 2, Loss: 0.10185, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 2, Loss: 0.10372, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 2, Loss: 0.10558, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 2, Loss: 0.10743, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 2, Loss: 0.10928, Batch_BER: 0.00500\n",
      "Iteration: 120, Epoch: 2, Loss: 0.11109, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 2, Loss: 0.11288, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 2, Loss: 0.11465, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 2, Loss: 0.11642, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 2, Loss: 0.11819, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 2, Loss: 0.11992, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 2, Loss: 0.12165, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 2, Loss: 0.12335, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 2, Loss: 0.12503, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 2, Loss: 0.12673, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 2, Loss: 0.12840, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 2, Loss: 0.13005, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 2, Loss: 0.13170, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 2, Loss: 0.13332, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 2, Loss: 0.13332, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 1/3\n",
      "Iteration: 10, Epoch: 1, Loss: 0.13285, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 1, Loss: 0.13238, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 1, Loss: 0.13192, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 1, Loss: 0.13145, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 1, Loss: 0.13099, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 1, Loss: 0.13054, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 1, Loss: 0.13008, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 1, Loss: 0.12963, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 1, Loss: 0.12918, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 1, Loss: 0.12873, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 1, Loss: 0.12829, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 1, Loss: 0.12785, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 1, Loss: 0.12741, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 1, Loss: 0.12698, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 1, Loss: 0.12655, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 1, Loss: 0.12612, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 1, Loss: 0.12569, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 1, Loss: 0.12527, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 1, Loss: 0.12485, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 1, Loss: 0.12443, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 1, Loss: 0.12401, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 1, Loss: 0.12360, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 1, Loss: 0.12319, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 1, Loss: 0.12279, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 1, Loss: 0.12238, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 1, Loss: 0.12238, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 2/3\n",
      "Iteration: 10, Epoch: 2, Loss: 0.12198, Batch_BER: 0.00500\n",
      "Iteration: 20, Epoch: 2, Loss: 0.12158, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 2, Loss: 0.12119, Batch_BER: 0.00500\n",
      "Iteration: 40, Epoch: 2, Loss: 0.12079, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 2, Loss: 0.12040, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 2, Loss: 0.12001, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 2, Loss: 0.11962, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 2, Loss: 0.11924, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 2, Loss: 0.11885, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 2, Loss: 0.11847, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 2, Loss: 0.11810, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 2, Loss: 0.11772, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 2, Loss: 0.11735, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 2, Loss: 0.11698, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 2, Loss: 0.11661, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 2, Loss: 0.11625, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 2, Loss: 0.11588, Batch_BER: 0.00500\n",
      "Iteration: 180, Epoch: 2, Loss: 0.11552, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 2, Loss: 0.11517, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 2, Loss: 0.11481, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 2, Loss: 0.11445, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 2, Loss: 0.11410, Batch_BER: 0.00000\n",
      "Iteration: 230, Epoch: 2, Loss: 0.11375, Batch_BER: 0.00000\n",
      "Iteration: 240, Epoch: 2, Loss: 0.11340, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 2, Loss: 0.11305, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 2, Loss: 0.11305, Batch_BER: 0.00000\n",
      "Training Bob in Epoch 3/3\n",
      "Iteration: 10, Epoch: 3, Loss: 0.11271, Batch_BER: 0.00000\n",
      "Iteration: 20, Epoch: 3, Loss: 0.11237, Batch_BER: 0.00000\n",
      "Iteration: 30, Epoch: 3, Loss: 0.11203, Batch_BER: 0.00000\n",
      "Iteration: 40, Epoch: 3, Loss: 0.11169, Batch_BER: 0.00000\n",
      "Iteration: 50, Epoch: 3, Loss: 0.11135, Batch_BER: 0.00000\n",
      "Iteration: 60, Epoch: 3, Loss: 0.11102, Batch_BER: 0.00000\n",
      "Iteration: 70, Epoch: 3, Loss: 0.11069, Batch_BER: 0.00000\n",
      "Iteration: 80, Epoch: 3, Loss: 0.11036, Batch_BER: 0.00000\n",
      "Iteration: 90, Epoch: 3, Loss: 0.11003, Batch_BER: 0.00000\n",
      "Iteration: 100, Epoch: 3, Loss: 0.10970, Batch_BER: 0.00000\n",
      "Iteration: 110, Epoch: 3, Loss: 0.10938, Batch_BER: 0.00000\n",
      "Iteration: 120, Epoch: 3, Loss: 0.10905, Batch_BER: 0.00000\n",
      "Iteration: 130, Epoch: 3, Loss: 0.10873, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 3, Loss: 0.10841, Batch_BER: 0.00000\n",
      "Iteration: 150, Epoch: 3, Loss: 0.10810, Batch_BER: 0.00000\n",
      "Iteration: 160, Epoch: 3, Loss: 0.10778, Batch_BER: 0.00000\n",
      "Iteration: 170, Epoch: 3, Loss: 0.10747, Batch_BER: 0.00000\n",
      "Iteration: 180, Epoch: 3, Loss: 0.10716, Batch_BER: 0.00000\n",
      "Iteration: 190, Epoch: 3, Loss: 0.10685, Batch_BER: 0.00000\n",
      "Iteration: 200, Epoch: 3, Loss: 0.10654, Batch_BER: 0.00000\n",
      "Iteration: 210, Epoch: 3, Loss: 0.10623, Batch_BER: 0.00000\n",
      "Iteration: 220, Epoch: 3, Loss: 0.10593, Batch_BER: 0.00500\n",
      "Iteration: 230, Epoch: 3, Loss: 0.10563, Batch_BER: 0.00500\n",
      "Iteration: 240, Epoch: 3, Loss: 0.10533, Batch_BER: 0.00000\n",
      "Iteration: 250, Epoch: 3, Loss: 0.10503, Batch_BER: 0.00000\n",
      "Interim result for Epoch: 3, Loss: 0.10503, Batch_BER: 0.00000\n",
      "Training Eve in Epoch 1/2\n",
      "Iteration: 10, Epoch: 1, Loss: 0.10825, Batch_BER: 0.25000\n",
      "Iteration: 20, Epoch: 1, Loss: 0.10914, Batch_BER: 0.07500\n",
      "Iteration: 30, Epoch: 1, Loss: 0.10937, Batch_BER: 0.05000\n",
      "Iteration: 40, Epoch: 1, Loss: 0.10943, Batch_BER: 0.05000\n",
      "Iteration: 50, Epoch: 1, Loss: 0.10940, Batch_BER: 0.04500\n",
      "Iteration: 60, Epoch: 1, Loss: 0.10934, Batch_BER: 0.03500\n",
      "Iteration: 70, Epoch: 1, Loss: 0.10921, Batch_BER: 0.00500\n",
      "Iteration: 80, Epoch: 1, Loss: 0.10908, Batch_BER: 0.00500\n",
      "Iteration: 90, Epoch: 1, Loss: 0.10896, Batch_BER: 0.04000\n",
      "Iteration: 100, Epoch: 1, Loss: 0.10881, Batch_BER: 0.01000\n",
      "Iteration: 110, Epoch: 1, Loss: 0.10868, Batch_BER: 0.00500\n",
      "Iteration: 120, Epoch: 1, Loss: 0.10850, Batch_BER: 0.00500\n",
      "Iteration: 130, Epoch: 1, Loss: 0.10835, Batch_BER: 0.01500\n",
      "Iteration: 140, Epoch: 1, Loss: 0.10818, Batch_BER: 0.01000\n",
      "Iteration: 150, Epoch: 1, Loss: 0.10802, Batch_BER: 0.03000\n",
      "Iteration: 160, Epoch: 1, Loss: 0.10787, Batch_BER: 0.00500\n",
      "Iteration: 170, Epoch: 1, Loss: 0.10770, Batch_BER: 0.02000\n",
      "Iteration: 180, Epoch: 1, Loss: 0.10756, Batch_BER: 0.02000\n",
      "Iteration: 190, Epoch: 1, Loss: 0.10741, Batch_BER: 0.03000\n",
      "Iteration: 200, Epoch: 1, Loss: 0.10728, Batch_BER: 0.03000\n",
      "Iteration: 210, Epoch: 1, Loss: 0.10710, Batch_BER: 0.01000\n",
      "Iteration: 220, Epoch: 1, Loss: 0.10692, Batch_BER: 0.00500\n",
      "Iteration: 230, Epoch: 1, Loss: 0.10677, Batch_BER: 0.01000\n",
      "Iteration: 240, Epoch: 1, Loss: 0.10662, Batch_BER: 0.02000\n",
      "Iteration: 250, Epoch: 1, Loss: 0.10647, Batch_BER: 0.01500\n",
      "Interim result for Epoch: 1, Loss: 0.10647, Batch_BER: 0.01500\n",
      "Training Eve in Epoch 2/2\n",
      "Iteration: 10, Epoch: 2, Loss: 0.10628, Batch_BER: 0.01000\n",
      "Iteration: 20, Epoch: 2, Loss: 0.10610, Batch_BER: 0.01000\n",
      "Iteration: 30, Epoch: 2, Loss: 0.10595, Batch_BER: 0.02500\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 40, Epoch: 2, Loss: 0.10579, Batch_BER: 0.01000\n",
      "Iteration: 50, Epoch: 2, Loss: 0.10564, Batch_BER: 0.02500\n",
      "Iteration: 60, Epoch: 2, Loss: 0.10546, Batch_BER: 0.01500\n",
      "Iteration: 70, Epoch: 2, Loss: 0.10530, Batch_BER: 0.01000\n",
      "Iteration: 80, Epoch: 2, Loss: 0.10514, Batch_BER: 0.01000\n",
      "Iteration: 90, Epoch: 2, Loss: 0.10497, Batch_BER: 0.02000\n",
      "Iteration: 100, Epoch: 2, Loss: 0.10479, Batch_BER: 0.00500\n",
      "Iteration: 110, Epoch: 2, Loss: 0.10461, Batch_BER: 0.01500\n",
      "Iteration: 120, Epoch: 2, Loss: 0.10445, Batch_BER: 0.00500\n",
      "Iteration: 130, Epoch: 2, Loss: 0.10428, Batch_BER: 0.00000\n",
      "Iteration: 140, Epoch: 2, Loss: 0.10414, Batch_BER: 0.01500\n",
      "Iteration: 150, Epoch: 2, Loss: 0.10396, Batch_BER: 0.01000\n",
      "Iteration: 160, Epoch: 2, Loss: 0.10381, Batch_BER: 0.02000\n",
      "Iteration: 170, Epoch: 2, Loss: 0.10367, Batch_BER: 0.01500\n",
      "Iteration: 180, Epoch: 2, Loss: 0.10349, Batch_BER: 0.01000\n",
      "Iteration: 190, Epoch: 2, Loss: 0.10333, Batch_BER: 0.01500\n",
      "Iteration: 200, Epoch: 2, Loss: 0.10317, Batch_BER: 0.02000\n",
      "Iteration: 210, Epoch: 2, Loss: 0.10299, Batch_BER: 0.00500\n",
      "Iteration: 220, Epoch: 2, Loss: 0.10284, Batch_BER: 0.01500\n",
      "Iteration: 230, Epoch: 2, Loss: 0.10268, Batch_BER: 0.00500\n",
      "Iteration: 240, Epoch: 2, Loss: 0.10254, Batch_BER: 0.01500\n",
      "Iteration: 250, Epoch: 2, Loss: 0.10238, Batch_BER: 0.02000\n",
      "Interim result for Epoch: 2, Loss: 0.10238, Batch_BER: 0.02000\n",
      "Mapping real symbols onto secure symbols\n",
      "Testing the secure symbols\n",
      "Progress: 1 of 30 parts\n",
      "Progress: 2 of 30 parts\n",
      "Progress: 3 of 30 parts\n",
      "Progress: 4 of 30 parts\n",
      "Progress: 5 of 30 parts\n",
      "Progress: 6 of 30 parts\n",
      "Progress: 7 of 30 parts\n",
      "Progress: 8 of 30 parts\n",
      "Progress: 9 of 30 parts\n",
      "Progress: 10 of 30 parts\n",
      "Progress: 11 of 30 parts\n",
      "Progress: 12 of 30 parts\n",
      "Progress: 13 of 30 parts\n",
      "Progress: 14 of 30 parts\n",
      "Progress: 15 of 30 parts\n",
      "Progress: 16 of 30 parts\n",
      "Progress: 17 of 30 parts\n",
      "Progress: 18 of 30 parts\n",
      "Progress: 19 of 30 parts\n",
      "Progress: 20 of 30 parts\n",
      "Progress: 21 of 30 parts\n",
      "Progress: 22 of 30 parts\n",
      "Progress: 23 of 30 parts\n",
      "Progress: 24 of 30 parts\n",
      "Progress: 25 of 30 parts\n",
      "Progress: 26 of 30 parts\n",
      "Progress: 27 of 30 parts\n",
      "Progress: 28 of 30 parts\n",
      "Progress: 29 of 30 parts\n",
      "Progress: 30 of 30 parts\n"
     ]
    }
   ],
   "source": [
    "train_Bob(n_epochs, n_steps, False, False)\n",
    "train_Eve(n_epochs-1, n_steps, False) #reduced epochs to match accuracy of both\n",
    "bber_data_bob, bber_data_eve = Test_AE(data_oh_normal) # Taking test data for comparison\n",
    "\n",
    "kmeans = init_kmeans(M,M_sec,n) # Initlizing kmeans for the security procedure\n",
    "train_Secure(kmeans.labels_, n_epochs-3, n_steps, 0.3, False)\n",
    "train_Bob(n_epochs-2, n_steps, False, True)\n",
    "train_Eve(n_epochs-3, n_steps, False)\n",
    "\n",
    "# test msg sequence for secure encoding\n",
    "N_test_sec = 150000\n",
    "test_msg_sec = np.random.randint(M_sec, size=N_test_sec)\n",
    "print('Mapping real symbols onto secure symbols')\n",
    "coded_msg, code_matrix = satellite_labels(kmeans.labels_, test_msg_sec,\n",
    "                                          M_sec, N_test_sec)\n",
    "one_hot_encoder_sec = OneHotEncoder(sparse=False, categories=[range(M)])\n",
    "data_oh_sec = one_hot_encoder_sec.fit_transform(coded_msg.reshape(-1,1))\n",
    "print(\"Testing the secure symbols\")\n",
    "bber_sec_bob, bber_sec_eve = Test_secure_AE(data_oh_sec, code_matrix, test_msg_sec)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "dark"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(8, 5))\n",
    "plt.semilogy(bber_data_bob[0], bber_data_bob[1], 'o-')\n",
    "plt.semilogy(bber_data_eve[0], bber_data_eve[1], 's-')\n",
    "plt.semilogy(bber_sec_bob[0], bber_sec_bob[1], '^-');\n",
    "plt.semilogy(bber_sec_eve[0], bber_sec_eve[1], '^-');\n",
    "\n",
    "plt.gca().set_ylim(1e-5, 1)\n",
    "plt.gca().set_xlim(0, 15)\n",
    "plt.tick_params(axis='x', colors='white')\n",
    "plt.tick_params(axis='y', colors='white')\n",
    "plt.ylabel(\"Batch Symbol Error Rate\", fontsize=14, rotation=90, color='white')\n",
    "plt.xlabel(\"SNR [dB]\", fontsize=18, color='white')\n",
    "plt.legend(['AE Bob', 'AE Eve', 'Secure AE Bob', 'Secure AE Eve'],\n",
    "           prop={'size': 14}, loc='upper right');\n",
    "plt.grid(True, which=\"both\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
